package com.mall.product.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Range;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.extra.compress.extractor.SevenZExtractor;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.common.constants.ProductConstants;
import com.common.dto.MemberPrice;
import com.common.dto.SkuHasStockDTO;
import com.common.dto.SkuReductionDTO;
import com.common.dto.SpuBoundsDTO;
import com.common.dto.es.SkuESModel;
import com.common.utils.R;
import com.mall.product.entity.*;
import com.mall.product.feign.CouponFeign;
import com.mall.product.feign.SearchFeignService;
import com.mall.product.feign.SeckillFeignService;
import com.mall.product.feign.WareFeign;
import com.mall.product.service.*;
import com.mall.product.vo.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.common.utils.PageUtils;
import com.common.utils.Query;

import com.mall.product.dao.SpuInfoDao;
import org.springframework.transaction.annotation.Transactional;


@Service("spuInfoService")
@Slf4j
public class SpuInfoServiceImpl extends ServiceImpl<SpuInfoDao, SpuInfoEntity> implements SpuInfoService {
    @Autowired
    private SpuInfoDescService spuInfoDescService;
    @Autowired
    private SpuImagesService spuImagesService;
    @Autowired
    private ProductAttrValueService productAttrValueService;
    @Autowired
    private AttrService attrService;
    @Autowired
    private SkuInfoService skuInfoService;
    @Autowired
    private SkuImagesService skuImagesService;
    @Autowired
    private SkuSaleAttrValueService skuSaleAttrValueService;
    @Autowired
    private CouponFeign couponFeign;
    @Autowired
    private CategoryService categoryService;
    @Autowired
    private BrandService brandService;
    @Autowired
    private WareFeign wareFeign;
    @Autowired
    private SearchFeignService searchFeignService;

    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<SpuInfoEntity> page = this.page(
                new Query<SpuInfoEntity>().getPage(params),
                new QueryWrapper<SpuInfoEntity>()
        );

        return new PageUtils(page);
    }

    /**
     * 保存商品上架发布信息
     * @param vo
     */
    @Override
    @Transactional
    public void saveSpuInfo(SpuInfoVo vo){
        //保存spu的基本信息
        SpuInfoEntity spuInfoEntity = new SpuInfoEntity();
        BeanUtils.copyProperties(vo,spuInfoEntity);
        Date date = new Date();
        spuInfoEntity.setCreateTime(date);
        spuInfoEntity.setUpdateTime(date);
        spuInfoEntity.setPublishStatus(0);
        this.save(spuInfoEntity);
        //保存spu的详情信息
        List<String> decript = vo.getDecript();
        SpuInfoDescEntity descEntity = new SpuInfoDescEntity();
        descEntity.setSpuId(spuInfoEntity.getId());
        descEntity.setDecript(String.join(",",decript));
        spuInfoDescService.save(descEntity);
        //保存图集信息
        List<String> images = vo.getImages();
        List<SpuImagesEntity> imagesList = images.stream().map(item -> {
            SpuImagesEntity imagesEntity = new SpuImagesEntity();
            imagesEntity.setSpuId(spuInfoEntity.getId());
            imagesEntity.setImgUrl(item);
            return imagesEntity;
        }).collect(Collectors.toList());
        spuImagesService.saveBatch(imagesList);
        //保存参数规格
        List<BaseAttrs> baseAttrs = vo.getBaseAttrs();
        List<ProductAttrValueEntity> productAttrValueEntities = baseAttrs.stream().map(item -> {
            ProductAttrValueEntity productAttrValueEntity = new ProductAttrValueEntity();
            productAttrValueEntity.setSpuId(spuInfoEntity.getId());
            productAttrValueEntity.setAttrId(item.getAttrId());
            productAttrValueEntity.setAttrValue(item.getAttrValues());
            AttrEntity attrEntity = attrService.getById(item.getAttrId());
            productAttrValueEntity.setAttrName(attrEntity.getAttrName());
            productAttrValueEntity.setQuickShow(item.getShowDesc());
            return productAttrValueEntity;
        }).collect(Collectors.toList());
        productAttrValueService.saveBatch(productAttrValueEntities);
        //保存Sku的基本信息
        List<Skus> skus = vo.getSkus();
        if (ObjectUtil.isNotNull(skus)){
            skus.forEach(item->{
                SkuInfoEntity skuInfoEntity = new SkuInfoEntity();
                BeanUtils.copyProperties(item,skuInfoEntity);
                skuInfoEntity.setBrandId(spuInfoEntity.getBrandId());
                skuInfoEntity.setCatalogId(spuInfoEntity.getCatalogId());
                skuInfoEntity.setSpuId(spuInfoEntity.getId());
                skuInfoEntity.setSaleCount(0L);
                List<com.mall.product.vo.images> itemImages = item.getImages();
                String defaultImg = "";
                for (com.mall.product.vo.images itemImage : itemImages) {
                    if (itemImage.getDefaultImag() == 1){
                        defaultImg = itemImage.getImgUrl();
                    }
                }
                skuInfoEntity.setSkuDefaultImg(defaultImg);
                skuInfoService.save(skuInfoEntity);
                //保存sku的图片信息
                List<SkuImagesEntity> imagesEntities = itemImages.stream().map(image -> {
                    SkuImagesEntity imagesEntity = new SkuImagesEntity();
                    imagesEntity.setSkuId(skuInfoEntity.getSkuId());
                    imagesEntity.setImgUrl(image.getImgUrl());
                    imagesEntity.setDefaultImg(image.getDefaultImag());
                    return imagesEntity;
                }).filter(img ->{
                    return img.getDefaultImg() == 1;
                }).collect(Collectors.toList());
                skuImagesService.saveBatch(imagesEntities);
                //保存满减信息
                SkuReductionDTO dto = new SkuReductionDTO();
                BeanUtils.copyProperties(item,dto);
                dto.setSkuId(skuInfoEntity.getSkuId());
                // 设置会员价
                if(item.getMemberPrice() != null && item.getMemberPrice().size() > 0){
                    List<com.common.dto.MemberPrice> list = item.getMemberPrice().stream().map(memberPrice -> {
                        MemberPrice mDto = new MemberPrice();
                        BeanUtils.copyProperties(memberPrice, mDto);
                        return mDto;
                    }).collect(Collectors.toList());
                    dto.setMemberPrices(list);
                }
                R r = couponFeign.saveFullReductionInfo(dto);
                if (r.getCode() != 0){
                    log.error("远程调用coupon服务错误");
                }
                //保存sku的销售属性
                List<Attr> attrs = item.getAttr();
                List<SkuSaleAttrValueEntity> skuSaleAttrValueEntities = attrs.stream().map(attr -> {
                    SkuSaleAttrValueEntity skuSaleAttrValueEntity = new SkuSaleAttrValueEntity();
                    BeanUtils.copyProperties(attr, skuSaleAttrValueEntity);
                    skuSaleAttrValueEntity.setSkuId(skuInfoEntity.getSkuId());
                    return skuSaleAttrValueEntity;
                }).collect(Collectors.toList());
                skuSaleAttrValueService.saveBatch(skuSaleAttrValueEntities);
            });
        }
        Bounds bounds = vo.getBounds();
        SpuBoundsDTO spuBoundsDTO = new SpuBoundsDTO();
        BeanUtils.copyProperties(bounds,spuBoundsDTO);
        spuBoundsDTO.setSpuId(spuBoundsDTO.getSpuId());
        R r = couponFeign.saveSpuBounds(spuBoundsDTO);
        if (r.getCode() != 0){
            log.error("调用coupon服务存储积分错误");
        }
    }

    /**
     * SPU信息检索
     * 分页查询
     * 分类 品牌 状态 关键字查询
     * @param params
     * @return
     */
    @Override
    public PageUtils queryPageByCondition(Map<String, Object> params) {
        QueryWrapper<SpuInfoEntity> wrapper = new QueryWrapper<>();
        // 设置对应的检索条件
        // 1. 关键字查询
        String key = (String) params.get("key");
        if(!StringUtils.isEmpty(key)){
            // 需要添加关键字查询
            wrapper.and((w)->{
                w.eq("id",key)
                        .or().like("spu_name",key)
                        .or().like("spu_description",key);
            });
        }
        // status
        String status = (String) params.get("status");
        if(!StringUtils.isEmpty(status)){
            wrapper.eq("publish_status",status);
        }
        // catalogId
        String catalogId = (String) params.get("catalogId");
        if(!StringUtils.isEmpty(catalogId) && !"0".equalsIgnoreCase(catalogId)){
            wrapper.eq("catalog_id",catalogId);
        }
        // brandId
        String brandId = (String) params.get("brandId");
        if(!StringUtils.isEmpty(brandId) && !"0".equalsIgnoreCase(brandId)){
            wrapper.eq("brand_id",brandId);
        }

        IPage<SpuInfoEntity> page = this.page(
                new Query<SpuInfoEntity>().getPage(params),
                wrapper
        );
        // 根据查询到的分页信息，再查询出对应的类别名称和品牌名称
        List<SpuInfoVo> list = page.getRecords().stream().map(spu -> {
            Long catalogId1 = spu.getCatalogId();
            CategoryEntity categoryEntity = categoryService.getById(catalogId1);
            Long brandId1 = spu.getBrandId();
            BrandEntity brandEntity = brandService.getById(brandId1);
            SpuInfoVo vo = new SpuInfoVo();
            log.info(String.valueOf(brandId1));
            BeanUtils.copyProperties(spu,vo);
            vo.setCatalogName(categoryEntity.getName());
            vo.setBrandName(brandEntity.getName());
            return vo;
        }).collect(Collectors.toList());
        IPage<SpuInfoVo> iPage = new Page<SpuInfoVo>();
        iPage.setRecords(list);
        iPage.setPages(page.getPages());
        iPage.setCurrent(page.getCurrent());
        return new PageUtils(iPage);
    }

    /**
     * 实现商品上架
     * @param spuId
     */
    @Override
    public void up(Long spuId) throws IOException {
        List<SkuESModel> list = new ArrayList<>();
        List<SkuInfoEntity> skuInfoEntities = skuInfoService.getSkuBySpuId(spuId);
        List<SkuESModel.Attrs> attrsList = getAttrs(spuId);
        List<Long> skuIds = skuInfoEntities.stream().map(SkuInfoEntity::getSkuId).collect(Collectors.toList());
        Map<Long, Boolean> map = getSkusHasStock(skuIds);
        List<SkuESModel> skuESModelList = skuInfoEntities.stream().map(item -> {
            SkuESModel skuESModel = new SkuESModel();
            BeanUtils.copyProperties(item,skuESModel);
            skuESModel.setSubTitle(item.getSkuTitle());
            skuESModel.setSubTitle(item.getSkuSubtitle());
            skuESModel.setSkuPrice(item.getPrice());
            skuESModel.setHotScore(0L);
            if (map == null){
                skuESModel.setHasStock(true);
            }
            else {
                skuESModel.setHasStock(map.get(item.getSkuId()));
            }
            BrandEntity brand = brandService.getById(item.getBrandId());
            CategoryEntity category = categoryService.getById(item.getCatalogId());
            skuESModel.setBrandName(brand.getName());
            skuESModel.setBrandImg(brand.getLogo());
            skuESModel.setCatalogName(category.getName());
            skuESModel.setAttrs(attrsList);
            return skuESModel;
        }).collect(Collectors.toList());
        R r = searchFeignService.productStatusUp(skuESModelList);
        if (r.getCode() == 0){
            baseMapper.updateSpuStatus(spuId, ProductConstants.StatusEnum.SPU_UP.getCode());
        }else {

        }
    }

    private List<SkuESModel.Attrs> getAttrs(Long spuId) {
        List<ProductAttrValueEntity> attrs = productAttrValueService.queryAttrsForSpuId(spuId);
        List<Long> attrIds = attrs.stream().map(ProductAttrValueEntity::getAttrId).collect(Collectors.toList());
        List<Long> searchAttrIds = attrService.selectSearchAttrIds(attrIds);
        List<SkuESModel.Attrs> attrsList = attrs.stream().filter(item -> {
            return searchAttrIds.contains(item.getAttrId());
        }).map(item -> {
            SkuESModel.Attrs atts = new SkuESModel.Attrs();
            atts.setAttrId(item.getAttrId());
            atts.setAttrName(item.getAttrName());
            atts.setAttrValue(item.getAttrValue());
            return atts;
        }).collect(Collectors.toList());
        return attrsList;
    }
    private Map<Long,Boolean> getSkusHasStock(List<Long> skuIds){
        List<SkuHasStockDTO> skuHasStock = null;
        if (skuIds == null && skuIds.isEmpty()){
            return null;
        }
        try {
            skuHasStock = wareFeign.getSkuHasStock(skuIds);
            Map<Long, Boolean> map = skuHasStock.stream().collect(Collectors.toMap(SkuHasStockDTO::getSkuId, SkuHasStockDTO::getHasStock));
            return map;
        }catch (Exception e){
            e.printStackTrace();
        }
        return null;
    }

    @Override
    public List<OrderItemSpuInfoVo> getOrderItemSpuInfoBySpuId(Long[] spuIds) {
        List<OrderItemSpuInfoVo> orderItemList = new ArrayList<>();
        for (Long spuId : spuIds) {
            OrderItemSpuInfoVo orderItemSpuInfoVo = new OrderItemSpuInfoVo();
            SpuInfoEntity spuInfo = this.getById(spuId);
            orderItemSpuInfoVo.setId(spuId);
            orderItemSpuInfoVo.setSpuName(spuInfo.getSpuName());
            orderItemSpuInfoVo.setBrandId(spuInfo.getBrandId());
            orderItemSpuInfoVo.setCatalogId(spuInfo.getCatalogId());
            BrandEntity brand = brandService.getById(spuInfo.getBrandId());
            orderItemSpuInfoVo.setBrandName(brand.getName());
            CategoryEntity category = categoryService.getById(spuInfo.getCatalogId());
            orderItemSpuInfoVo.setCatalogName(category.getName());
            SpuInfoDescEntity descEntity = spuInfoDescService.getById(spuId);
            orderItemSpuInfoVo.setImg(descEntity.getDecript());
            orderItemList.add(orderItemSpuInfoVo);
        }
        return orderItemList;
    }
}